package cc.autoapi.pucong.auto.flow.core.flow.execNode.task.system;


import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.node.*;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.task.ApiExecResult;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.exception.AutoDesignException;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.exec.DataBus;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.exec.ProcessExecStart;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.selfenum.NodeTypeEnum;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.selfenum.ParamPositionEnum;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.selfenum.RunStatusEnum;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.task.AbstractTask;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ProcessTask extends AbstractTask {

    private List<NodeParamIn> paramsIns;
    private List<NodeParamOut> paramsOuts;

    public ProcessTask() {
        paramsIns = new ArrayList<>();

        paramsOuts = new ArrayList<>();
    }

    @Override
    public void run() {
        ExecNodeProcess execNode = (ExecNodeProcess) getExecNode();
        String processId = execNode.getProcessId();
        if (StringUtils.isBlank(processId)) {
            throw new AutoDesignException("执行子流程为空！,节点名称：" + execNode.getNodeName());
        }
        List<TaskNode> taskNodeList = DataBus.getTaskNodeList(processId);
        TaskNode taskNode = taskNodeList.stream().filter(node -> NodeTypeEnum.API_CONFIG.getKey().equals(node.getNodeType()) || NodeTypeEnum.CRON_CONFIG.getKey().equals(node.getNodeType())).findFirst().orElse(null);
        if (taskNode == null) {
            throw new AutoDesignException("找不到子流程！,节点名称：" + execNode.getNodeName());
        }
        // 同步执行
        Future<ApiExecResult> apiExecResultFuture = processExec(processId);
        ApiExecResult result = null;
        try {
            result = apiExecResultFuture.get(30, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("执行子流程异常: ", e);
            throw new AutoDesignException("执行子流程异常:" + e.getMessage());
        }
        RunStatusEnum runStatus = result.getRunStatus();
        List<ExecParamOut> paramOutList = execNode.getParamOutList();

        if (runStatus == RunStatusEnum.执行成功) {
            Object data = result.getData();
            Object parse = JSON.toJSON(data);
            if (!(parse instanceof JSONObject)) {
                throw new AutoDesignException("子流程输出参数错误，只能是对象");
            }
            JSONObject jsonObject = (JSONObject) parse;
            for (ExecParamOut execParamOut : paramOutList) {
                String paramCode = execParamOut.getParamCode();
                setParamOutValue(paramCode, jsonObject.get(paramCode));
            }
        } else if (runStatus == RunStatusEnum.执行失败) {
            throw new AutoDesignException(result.getErrorLog());
        }
    }

    public Future<ApiExecResult> processExec(String processId) {
        List<TaskNode> taskNodeList = DataBus.getTaskNodeList(processId);
        ExecNode execNode = getExecNode();
        if (taskNodeList == null || taskNodeList.size() == 0) {
            String nodeName = execNode.getNodeName();
            throw new AutoDesignException("该子流程的服务未发布，节点名称：" + nodeName);
        }
        List<ExecParamIn> paramInList = execNode.getParamInList();
        Map<String, Object> queryMap = new HashMap<>(16);
        Map<String, String> headerMap = new HashMap<>(16);
        Map<String, Object> bodyMap = new HashMap<>(16);
        for (ExecParamIn execParamIn1 : paramInList) {
            String paramCode = execParamIn1.getParamCode();
            Object dateValue1 = execParamIn1.getDateValue();
            ParamPositionEnum paramPosition = execParamIn1.getParamPosition();
            switch (paramPosition) {
                case QUERY:
                    queryMap.put(paramCode, dateValue1);
                    break;
                case BODY:
                    bodyMap.put(paramCode, dateValue1);
                    break;
                case HEADER:
                    headerMap.put(paramCode, dateValue1.toString());
                    break;
                default:
                    throw new AutoDesignException("传入参数位置错误");
            }
        }
        // 创建实例信息
        String instanceId = UUID.randomUUID().toString();
        // 开始执行
        ProcessExecStart processExecStart = new ProcessExecStart(processId, instanceId, queryMap, headerMap, bodyMap);
        Future<ApiExecResult> apiExecResultFuture = processExecStart.startFuture();
        return apiExecResultFuture;
    }

    @Override
    public String getTaskName() {
        return "子流程执行";
    }

    @Override
    public String getTaskDesc() {
        return "本组件有processId属性，是子流程的id，执行该组件会启动执行一个子流程，且会等待子流程执行完成，本组件状态才会变为执行完成。";
    }

    @Override
    public String getTaskSvgIcon() {
        return "<svg t=\"1727021052817\" class=\"icon\" viewBox=\"0 0 1189 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"59773\" width=\"32\" height=\"32\"><path d=\"M253.58081468 674.00447026l304.37453425-151.86821817 45.94332584 92.20570415-304.37453427 151.86821585-45.94332582-92.20570183z m0 0\" fill=\"#87E8DE\" p-id=\"59774\"></path><path d=\"M535.30273615 533.62208473L895.51117353 209.785446l68.91498877 76.57221049-360.52748753 323.83663874-68.59593862-76.5722105z m0 0\" fill=\"#87E8DE\" p-id=\"59775\"></path><path d=\"M551.57433004 610.19429523l56.79105585-86.14373764 344.25589365 226.84517333-56.79105585 86.14373535-344.25589365-226.84517104z m0 0\" fill=\"#87E8DE\" p-id=\"59776\"></path><path d=\"M424.91113269 573.184394c0 51.68624214 27.43837634 99.22482096 72.10549935 125.06794203s99.54387346 25.84312106 144.2109941 0c44.66712298-25.84312106 72.10549702-73.3817022 72.10549703-125.06794203s-27.43837634-99.22482096-72.10549703-125.06794436-99.54387346-25.84312106-144.2109941 0c-44.34807053 25.84312106-72.10549702 73.3817022-72.10549935 125.06794436z m0 0M172.54189073 944.24055911c-92.84380438 0-170.05411518-77.21031077-170.05411517-170.05411518s77.21031077-170.05411518 170.05411517-170.05411517 170.05411518 77.21031077 170.05411748 170.05411517c-5.10481373 92.52475427-77.21031077 170.05411518-170.05411748 170.05411518z m0-231.94998476c-36.0527485 0-67.00068334 30.94793478-67.00068336 67.00068335 0 36.0527485 30.94793478 67.00068334 67.00068336 67.00068329 36.0527485 0 67.00068334-30.94793478 67.00068561-67.00068329 0-36.0527485-30.94793478-67.00068334-67.00068561-67.00068335zM1017.70765972 336.1295932c-92.84380438 0-170.05411518-77.21031077-170.05411746-170.05411517S925.1829055-3.97863943 1017.70765972-3.97863943c92.84380438 0 170.05411518 77.21031077 170.05411518 170.05411746s-77.52936321 170.05411518-170.05411518 170.05411517z m0-231.94998476c-36.0527485 0-67.00068334 30.94793478-67.00068562 67.00068333 0 36.0527485 30.94793478 67.00068334 67.00068562 67.00068332 36.0527485 0 67.00068334-30.94793478 67.00068333-67.00068332 0-41.15756225-30.94793478-67.00068334-67.00068333-67.00068333z m0 922.37607745c-92.84380438 0-170.05411518-77.21031077-170.05411746-170.05411514s77.52936321-170.05411518 170.05411746-170.05411744c92.84380438 0 170.05411518 77.21031077 170.05411518 170.05411744S1110.23241168 1026.55568589 1017.70765972 1026.55568589z m0-237.05480076c-36.0527485 0-67.00068334 30.94793478-67.00068562 67.00068562 0 36.0527485 30.94793478 67.00068334 67.00068562 67.00068333 36.0527485 0 67.00068334-30.94793478 67.00068333-67.00068333 0-36.0527485-30.94793478-67.00068334-67.00068333-67.00068562z m0 0\" fill=\"#13C2CC\" p-id=\"59777\"></path></svg>";
    }

    @Override
    public List<NodeParamIn> getPropertyParamsIns() {
        return paramsIns;
    }

    @Override
    public List<NodeParamOut> getPropertyParamsOuts() {
        return paramsOuts;
    }
}
